//
//  bleIOSSdk.m
//  bleIOSSdk
//
//  Created by 董海伟 on 2019/2/6.
//  Copyright © 2019 董海伟. All rights reserved.
//

#import "bleIOSSdk.h"
#include "btinterface.h"
#include "BtMsghandler.h"
#include "hzkHandler.h"
#ifdef MINI_GLOG
#include "miniglog/logging.h"
#endif
#import "SDKHeader.h"

BtSdkListener *gpListener = NULL;
IBtSdkInterface *gpHandler = NULL;
bool gInit = false;

@interface bleIOSSdk ()
@property(assign, nonatomic) CBCharacteristic *writecharacteristic;
@property(strong,nonatomic) CBPeripheral *currPeripheral;
@end

@implementation bleIOSSdk

- (BabyBluetooth*) getBluetoothPtr
{
    return [BabyBluetooth shareBabyBluetooth];
}

- (void) initSdk: (NSString *) strHzkFileName 
{
    if(gInit) {
        LOG(INFO)<<"sdk is already init.";
        return;
    } else {
        gInit = true;
    }
	const char * csFileName =[strHzkFileName UTF8String];
    setHzkFileName(csFileName);
    BabyBluetooth *baby = [self getBluetoothPtr];
    if(Nil != baby) {
        //停止之前的连接
        [baby cancelAllPeripheralsConnection];
        //设置委托后直接可以使用，无需等待CBCentralManagerStatePoweredOn状态。
        baby.scanForPeripherals().begin();
        //baby.scanForPeripherals().begin().stop(10);
    }
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(sendToBaseBle:)
                                                 name:SEND_TO_BASE_BLE object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(onSendDataResult:)
                                                 name:ON_SEND_DATA_RESULT object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(onRecvBleData:)
                                                 name:ON_RECV_BEL_DATA object:nil];
}

- (void) sendData: (NSData *) businessData withTid: (char) tid withSid: (char) sid
{
    if(!gInit) {
        LOG(INFO)<<"sdk is uninit.";
        return;
    }
    
    DataInfo info((int)businessData.length,tid,sid);
    gpHandler->sendData((const unsigned char*)businessData.bytes, &info);
}

- (void) unInitSdk
{
    if(!gInit) {
        LOG(INFO)<<"sdk is uninit.";
        return;
    } else {
        gInit = false;
    }
    
    BabyBluetooth *baby = [self getBluetoothPtr];
    if(Nil != baby) {
        //停止之前的连接
        [baby cancelAllPeripheralsConnection];
        //设置委托后直接可以使用，无需等待CBCentralManagerStatePoweredOn状态。
        [baby stop];
    }
    
    if(NULL != gpHandler) {
        delete gpHandler;
        gpHandler = NULL;
    }
    
    if(NULL != gpListener) {
        delete gpListener;
        gpListener = NULL;
    }
    
    [[NSNotificationCenter defaultCenter] removeObserver: self];
}

- (void) connectDevice: (CBPeripheral *)currPeripheral
{
    if(!gInit) {
        LOG(INFO)<<"sdk is uninit.";
        return;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if(NULL == gpHandler) {
            gpHandler = new BtMsghandler();
            
            if(NULL == gpListener) {
                gpListener  = new BtSdkListener();
            }
            
            gpHandler->setListener(gpListener);
        }
    });
    
    self.currPeripheral = currPeripheral;
    
    BabyBluetooth *baby = [self getBluetoothPtr];
    if(Nil != baby) {
        //设置设备连接成功的委托,同一个baby对象，使用不同的channel切换委托回调
        [baby setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
            if(nil != self.delegate && [self.delegate respondsToSelector:@selector(onConnec:)]) {
                [self.delegate onConnec: ERR_SUCCESS];
            }
        }];
        
        //设置设备连接失败的委托
        [baby setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
            if(nil != self.delegate && [self.delegate respondsToSelector:@selector(onConnec:)]) {
                [self.delegate onConnec: ERR_FAILED];
            }
        }];
        
        [baby setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
            NSLog(@"characteristic name:%@ value is ===: %@", characteristic.UUID.UUIDString, characteristic.value);
            
            if ([characteristic.UUID.UUIDString isEqualToString:@"FFE1"]) {
                if(NULL != gpHandler) {
                    //NSString *recv = [bleIOSSdk stringFromHexString: [bleIOSSdk hexStringWithData:characteristic.value]];
                    gpHandler->handleBaseBlePackage((const unsigned char*)characteristic.value.bytes, (const int)characteristic.value.length);
                }
            }
        }];
        
        //设置发现设备的Services的委托
        [baby setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
            NSLog(@"===service name:%@", service.UUID);
            for (CBCharacteristic *c in service.characteristics)
            {
                NSLog(@"===c UUID:%@", c.UUID.UUIDString);
                
                if ([c.UUID.UUIDString isEqualToString:@"FFE1"]) {
                    self.writecharacteristic = c;
                    
                    [peripheral setNotifyValue:YES forCharacteristic: c];
                    
                    [self.delegate onConnec: ERR_CAN_SENDDATA];
                }
            }
        }];
        
        [baby setBlockOnDidWriteValueForCharacteristic:^(CBCharacteristic *characteristic, NSError *error) {
            int result = SENDRLT_SRVFAIL;
            if (nil == error) {
                result = SENDRLT_SUCC;
                NSLog(@"===setBlockOnDidWriteValueForCharacteristic success!");
            } else {
                NSLog(@"===setBlockOnDidWriteValueForCharacteristic err:%@", error);
            }
            
            gpHandler->onNotifySendToBaseBleResult(result);
        }];
        
        baby.having(currPeripheral);
        baby.connectToPeripherals();
        baby.discoverServices();
        baby.discoverCharacteristics();
        baby.readValueForCharacteristic();
        baby.discoverDescriptorsForCharacteristic();
        baby.readValueForDescriptors();
        baby.begin();
        
        /*self.baby.having(self.currPeripheral).and.then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
         */
    } else {
        [self.delegate onConnec: ERR_FAILED];
    }
}

+ (NSString *) hexStringWithData:(NSData *)data
{
    const unsigned char* dataBuffer = (const unsigned char*)[data bytes];
    if(!dataBuffer){
        return nil;
    }
    NSUInteger dataLength = [data length];
    NSMutableString* hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
    for(int i = 0; i < dataLength; i++){
        [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
    }
    NSString* result = [NSString stringWithString:hexString];
    return result;
}

+ (NSData *) converHexStrToData: (NSString *) str {
    if (!str || [str length] == 0) {
        return nil;
    }
    
    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
    NSRange range;
    if([str length] % 2 == 0) {
        range = NSMakeRange(0, 2);
    } else {
        range = NSMakeRange(0, 1);
    }
    
    for (NSInteger i = range.location; i < [str length]; i += 2) {
        unsigned int anInt;
        NSString *hexCharStr = [str substringWithRange: range];
        NSScanner *scanner = [[NSScanner alloc] initWithString: hexCharStr];
        
        [scanner scanHexInt: &anInt];
        NSData *entity = [[NSData alloc] initWithBytes: &anInt length:1];
        [hexData appendData: entity];
        
        range.location += range.length;
        range.length = 2;
    }
    
    NSLog(@"hexdata: %@", hexData);
    return hexData;
}

+ (NSString *)stringFromHexString:(NSString *)hexString {
    
    char *myBuffer = (char *)malloc((int)[hexString length] / 2 + 1);
    bzero(myBuffer, [hexString length] / 2 + 1);
    for (int i = 0; i < [hexString length] - 1; i += 2) {
        unsigned int anInt;
        NSString * hexCharStr = [hexString substringWithRange:NSMakeRange(i, 2)];
        NSScanner * scanner = [[NSScanner alloc] initWithString:hexCharStr];
        [scanner scanHexInt:&anInt];
        myBuffer[i / 2] = (char)anInt;
    }
    NSString *unicodeString = [NSString stringWithCString:myBuffer encoding:4];
    return unicodeString;
}

-(void) sendToBaseBle: (NSNotification*) note {
    NSData *data = [note object];
    if(nil != data) {
         [self.currPeripheral writeValue: data forCharacteristic:self.writecharacteristic type: CBCharacteristicWriteWithResponse];
    }
}

- (DataInfoOC*) getDataInfoOCFromRecv:(NSDictionary *)recv {
    DataInfoOC *info = nil;
    if(nil != recv) {
        info = [[DataInfoOC alloc] init];
        NSNumber *dataLenNum = [recv objectForKey: @"dataLen"];
        if (nil != dataLenNum) {
            [info setDataLen: [dataLenNum intValue]];
        }
        
        NSNumber *taskIdNum = [recv objectForKey: @"taskId"];
        if (nil != taskIdNum) {
            [info setTaskId: [taskIdNum charValue]];
        }
        
        NSNumber *storeIdNum = [recv objectForKey: @"storeId"];
        if (nil != storeIdNum) {
            [info setStoreId: [storeIdNum charValue]];
        }
    }
    
    return info;
}

- (void) onSendDataResult: (NSNotification*) note {
    NSDictionary *recv = [note object];
    if(nil != recv) {
        int retCode=1;
        NSNumber *storeIdNum = [recv objectForKey: @"retCode"];
        if(nil != storeIdNum) {
            retCode = [storeIdNum intValue];
        }
        
        DataInfoOC *info = [self getDataInfoOCFromRecv: recv];
        if(nil != info) {
            if(nil != self.delegate && [self.delegate respondsToSelector:@selector(onSendDataResult:with:)]) {
                [self.delegate onSendDataResult: retCode with:info];
            }
        }
    }
}

- (void) onRecvBleData: (NSNotification*) note {
    NSDictionary *recv = [note object];
    if(nil != recv) {
        NSData *businessData = [recv objectForKey: @"businessData"];
        if(nil != businessData) {
            DataInfoOC *info = [self getDataInfoOCFromRecv: recv];
            if(nil != info) {
                if(nil != self.delegate && [self.delegate respondsToSelector:@selector(onRecvBleData:with:)]) {
                    [self.delegate onRecvBleData:businessData with:info];
                }
            }
        }
    }
}

@end
